package com.specter.utils;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.DateFormat;

// import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import lombok.extern.slf4j.Slf4j;

/**
 * Note:对webservice中自定义的XML字符串进行解析
 * 
 * @author Liang.Wang
 * @version Sep 8, 2010 10:06:54 AM
 */
@Slf4j
public class DOMUtils {

	private DOMUtils() {

	}

	/**
	 * 解析XML文档对象
	 * 
	 * @param xml XML字符串
	 * @return DOM对象
	 */
	public static Document parse(String xml) {
		org.w3c.dom.Document doc = null;
		try (InputStream is = new ByteArrayInputStream(xml.getBytes());) {

			DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
			// df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
			// df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
			DocumentBuilder builder = df.newDocumentBuilder();
			doc = builder.parse(is);

		} catch (Exception e) {
			log.error("XML字符串解析错误，检查是否按照格式!");
			e.printStackTrace();
		}
		return doc;
	}

	/**
	 * 将XML字符串解析成RootElement
	 * 
	 * @param xml
	 * @return
	 */
	public static Element parseRoot(String xml) {
		Document doc = parse(xml);
		Element root = null;
		if (doc != null) {
			root = doc.getDocumentElement();
		}

		return root;
	}

	/**
	 * 根据路径解析XML dir:开头的为绝对路径 否则为类相对路径
	 * 
	 * @param path 文件路径
	 * @return
	 */
	public static Document read(String path) {
		String file = path.startsWith("dir:") ? System.getProperty("user.dir") + path.substring(4) : path;
		Document doc = null;
		try (InputStream is = file.equals(path) ? DOMUtils.class.getResourceAsStream(path)
				: new FileInputStream(file)) {

			DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
			// df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
			// df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
			DocumentBuilder builder = df.newDocumentBuilder();
			doc = builder.parse(is);

		} catch (Exception e) {
			log.error("configuration file read error!");
			e.printStackTrace();
		}
		return doc;
	}

	/**
	 * 将一个标签转换成一个实体
	 * 
	 * @param <T>
	 * @param clazz
	 * @param element
	 * @return
	 */
	public static <T> T toBean(Class<T> clazz, Element element) {
		T t = null;
		try {

			t = clazz.getDeclaredConstructor().newInstance();
			NodeList nl = element.getChildNodes();

			Field f = null;
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				f = clazz.getDeclaredField(node.getNodeName());
				Object text = node.getNodeValue();
				if (java.util.Date.class.isAssignableFrom(f.getType())) {
					text = DateFormat.getInstance().parse(text.toString());
				}
				f.set(t, text);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}
}
